﻿using Flurl;
using Flurl.Http;
using Microsoft.Extensions.Configuration;
using Mirai.Net.Api.Contract;
using Serilog;
using System;
using System.Diagnostics;
using System.Text.Json;
using System.Threading.Tasks;
using JsonSerializer = System.Text.Json.JsonSerializer;

namespace Mirai.Net.Core
{
    public class MiraiClient
    {
        private static JsonSerializerOptions options = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        };
        private static string sessionKey;
        private static string host = "http://"+Environment.GetEnvironmentVariable("MIRAI_CORE");

        public Task<FetchMessageResponse> FetchMessagesAsync()
        {
            return InvokeGetApiAsync<FetchMessageResponse>("fetchMessage", new
            {
                sessionKey = sessionKey,
                count = 10
            });
        }

        private static bool verified;

        public static bool Verified { get => verified; set => verified = value; }

        public MiraiClient()
        {
        }

        private async Task<TResponse> InvokePostApiAsync<TResponse>(string path, object request)
        {
            try
            {
                var requestContent = JsonSerializer.Serialize(request, new JsonSerializerOptions()
                {
                    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                });
                return await (await host.AppendPathSegment(path)
                    .WithHeader("content-type", "application/json")
                    .PostStringAsync(requestContent)).GetJsonAsync<TResponse>();
            }
            catch (FlurlHttpException e)
            {
                Log.Error(e, "异常");
                var responseString = await e.GetResponseStringAsync();
                throw new Exception(responseString);
            }
        }
        private async Task<TResponse> InvokeGetApiAsync<TResponse>(string path, object values)
        {
            try
            {
                return await host.AppendPathSegment(path).SetQueryParams(values).GetJsonAsync<TResponse>();
            }
            catch (FlurlHttpException e)
            {
                var responseString = await e.GetResponseStringAsync();
                throw new Exception(responseString);
            }
        }

        public async Task ConnectAsync()
        {
            if (!string.IsNullOrWhiteSpace(sessionKey))
            {
                return;
            }
            Log.Information("开始连接");
            var authResponse = await InvokePostApiAsync<AuthResponse>("verify", new
            {
                verifyKey = Environment.GetEnvironmentVariable("MIRAI_VERIFYKEY")
            });
            if (authResponse.Code != 0)
            {
                Log.Error("Mirai.Verfy失败");
                return;
            }
            sessionKey = authResponse.Session;
        }

        public async Task AgreeMemberJoinGroupAsync(string eventId, string fromId, string groupId, int operate, string message)
        {
            await InvokePostApiAsync<AuthResponse>("/resp/memberJoinRequestEvent", new
            {
                sessionKey,
                eventId,
                fromId,
                groupId,
                operate,
                message = message
            });
        }
        public async Task AgreeNewFriendAsync(string eventId, string fromId, string groupId, int operate, string message)
        {
            await InvokePostApiAsync<AuthResponse>("/resp/newFriendRequestEvent", new
            {
                sessionKey,
                eventId,
                fromId,
                groupId,
                operate,
                message = message
            });
        }

        public async Task SendFriendMessageAsync(string qq, string message)
        {
            var authResponse = await InvokePostApiAsync<AuthResponse>("sendFriendMessage", new
            {
                sessionKey = sessionKey,
                target = Convert.ToUInt64(qq),
                messageChain = new object[]
                {
                    new
                    {
                        type="Plain",
                        text=message
                    }
                }
            });
        }

        public async Task SendGroupMessageAsync(string qq, string message)
        {
            var authResponse = await InvokePostApiAsync<AuthResponse>("sendGroupMessage", new
            {
                sessionKey = sessionKey,
                target = Convert.ToUInt64(qq),
                messageChain = new object[]
                {
                    new
                    {
                        type="Plain",
                        text=message
                    }
                }
            });
        }

        public async ValueTask VerifyAsync(string qq)
        {
            if (verified)
            {
                return;
            }
            var authResponse = await InvokePostApiAsync<AuthResponse>("bind", new
            {
                sessionKey = sessionKey,
                qq = qq
            });
            if (authResponse.Code != 0)
            {
                Debugger.Break();
            }
            verified = true;
        }
    }
}
